﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Net;
using System.IO;
using System.Collections;

namespace 一起来击键
{

    public partial class 数码输入窗体 : Form
    {

        DateTime startTime;
        int s = 0;                              //定义已用时间
        int b = 0;                               //定义总时间
        private string user_input = "";         //定义当前富文本框用户输入的内容
        private int sudu_ = 0, time_;              //
        int len1 = 1, len2 = 0;                 //定义两个与计时相关的标志
        int page = 1;                           //定义页码，初始为第一页
        int flag_begin = 0;                     //定义计时开始标志
        private int user_input_nums;            //定义用户输入的数码组数
        string[] shuzu = new string[1024];      //定义生成数码
        string[] shuzu2 = new string[1024];     //定义用户输入的数码

        ArrayList shumalist = new ArrayList();  //定义存储再现过程的内容
        ArrayList timelist = new ArrayList();  //定义存储再现过程中的时刻信息


        int flag_bn = 0;                        //定义重新开始的标志
        int flag_reappear = 0;                  //定义再现过程的标志
        int flag_time_stop = 1;                 //定义停止计时的标志

        [DllImport("user32", EntryPoint = "HideCaret")]      //导入隐藏富文本框中光标的组件
        private static extern bool HideCaret(IntPtr hWnd);

        public 数码输入窗体()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            ThreadStart childref3 = new ThreadStart(jisuan);  //开启计算线程
            Thread childThread3 = new Thread(childref3);
            childThread3.Start();
            ThreadStart childref1 = new ThreadStart(guangbiao);  //开启光标闪烁线程
            Thread childThread1 = new Thread(childref1);
            childThread1.Start();
            ThreadStart childref2 = new ThreadStart(reappear);  //开启再现过程线程
            Thread childThread2 = new Thread(childref2);
            childThread2.Start();
        }

        void guangbiao()//光标闪烁线程
        {
            //光标闪烁间隔设置为1000ms
            while (true)
            {
                Thread.Sleep(500);
                try
                {
                    if (richTextBox2.Text.Substring(richTextBox2.Text.Length - 1, 1) != "_")
                        richTextBox2.AppendText("_");
                    Thread.Sleep(500);
                    if (richTextBox2.Text.Substring(richTextBox2.Text.Length - 1, 1) == "_")
                        richTextBox2.Text = richTextBox2.Text.Substring(0, richTextBox2.Text.Length - 1);
                }
                catch
                { }
            }
        }

        string suijishu()//借助随机函数，产生4个一组的数码
        {
            byte[] randomBytes = new byte[4];
            RNGCryptoServiceProvider rngServiceProvider = new RNGCryptoServiceProvider();
            rngServiceProvider.GetBytes(randomBytes);
            string result = BitConverter.ToInt32(randomBytes, 0).ToString();
            if (result.Length < 5) result = "00000";     //容错处理
            string shuma = result.Substring(1, 4);
            return shuma;

        }

        void conduct_shuzu()//随机产生9900组数码
        {
            for (int k = 1; k <= 99; k++)
            {
                for (int i = 0; i < 10; i++)
                {
                    shuzu[k] = shuzu[k] + " ";

                    for (int j = 0; j < 10; j++)
                    {
                        shuzu[k] = shuzu[k] + suijishu() + " ";

                        if (j == 4)
                            shuzu[k] = shuzu[k] + " ";
                    }
                    if (i != 9)
                        shuzu[k] = shuzu[k] + "\n";
                }
            }
        }

        int get_zushu(string strSource)  //计算用户输入数码的组数
        {

            char[] s = strSource.ToCharArray();  //将字符串对象中的字符转换为一个字符数组

            int count = 0;
            for (int i = 0; i < s.Length; i++)
                if (s[i] >= 48 && s[i] <= 57)
                    count++;

            count = count / 4;                 //计算当前页面数码的组数
            count = (page - 1) * 100 + count; //之前的页面数码的总数与当前页面数码的合计
            user_input_nums = count;
            return count;

        }

        void jisuan()  //计算时间，计算组数，算出速度
        {
            while (true)
            {
                while (s <= b & flag_time_stop == 0)
                {
                    time_ = s;
                    label24.Text = "用时：" + s + " 秒";

                    if (checkBox1.Checked == false)
                        label25.Text = "剩余：∞ 秒";
                    else
                        label25.Text = "剩余：" + (b - s) + " 秒";
                    double sudu = get_zushu(user_input) / (s + 0.0001) * 360;
                    label26.Text = "速度：" + ((int)sudu).ToString();
                    sudu_ = ((int)sudu);
                    label28.Text = "组数：" + get_zushu(user_input).ToString();
                    Thread.Sleep(999);
                    if (len2 != 0)
                    {
                        s = s + 1;
                    }
                }
                Thread.Sleep(1000);  //检测
            }
            MethodInvoker mi = new MethodInvoker(show_check);
            BeginInvoke(mi);
        }

        private void pageTolable(int Page_pageTolable)    //根据页码显示每一页的lable标签值
        {
            Page_pageTolable = Page_pageTolable - 1;
            if (Page_pageTolable < 9)
            {
                label1.Text = "0" + Page_pageTolable.ToString() + "1-";
                label2.Text = "0" + Page_pageTolable.ToString() + "2-";
                label3.Text = "0" + Page_pageTolable.ToString() + "3-";
                label4.Text = "0" + Page_pageTolable.ToString() + "4-";
                label5.Text = "0" + Page_pageTolable.ToString() + "5-";
                label6.Text = "0" + Page_pageTolable.ToString() + "6-";
                label7.Text = "0" + Page_pageTolable.ToString() + "7-";
                label8.Text = "0" + Page_pageTolable.ToString() + "8-";
                label9.Text = "0" + Page_pageTolable.ToString() + "9-";
                label10.Text = "0" + (Page_pageTolable + 1).ToString() + "0-";

                label20.Text = "0" + Page_pageTolable.ToString() + "1-";
                label19.Text = "0" + Page_pageTolable.ToString() + "2-";
                label18.Text = "0" + Page_pageTolable.ToString() + "3-";
                label17.Text = "0" + Page_pageTolable.ToString() + "4-";
                label16.Text = "0" + Page_pageTolable.ToString() + "5-";
                label15.Text = "0" + Page_pageTolable.ToString() + "6-";
                label14.Text = "0" + Page_pageTolable.ToString() + "7-";
                label13.Text = "0" + Page_pageTolable.ToString() + "8-";
                label12.Text = "0" + Page_pageTolable.ToString() + "9-";
                label11.Text = "0" + (Page_pageTolable + 1).ToString() + "0-";
            }
            else if (Page_pageTolable == 9)
            {
                label1.Text = "091-";
                label2.Text = "092-";
                label3.Text = "093-";
                label4.Text = "094-";
                label5.Text = "095-";
                label6.Text = "096-";
                label7.Text = "097-";
                label8.Text = "098-";
                label9.Text = "099-";
                label10.Text = "100-";

                label20.Text = "091-";
                label19.Text = "092-";
                label18.Text = "093-";
                label17.Text = "094-";
                label16.Text = "095-";
                label15.Text = "096-";
                label14.Text = "097-";
                label13.Text = "098-";
                label12.Text = "099-";
                label11.Text = "100-";
            }
            else
            {
                label1.Text = Page_pageTolable.ToString() + "1-";
                label2.Text = Page_pageTolable.ToString() + "2-";
                label3.Text = Page_pageTolable.ToString() + "3-";
                label4.Text = Page_pageTolable.ToString() + "4-";
                label5.Text = Page_pageTolable.ToString() + "5-";
                label6.Text = Page_pageTolable.ToString() + "6-";
                label7.Text = Page_pageTolable.ToString() + "7-";
                label8.Text = Page_pageTolable.ToString() + "8-";
                label9.Text = Page_pageTolable.ToString() + "9-";
                label10.Text = (Page_pageTolable + 1).ToString() + "0-";

                label20.Text = Page_pageTolable.ToString() + "1-";
                label19.Text = Page_pageTolable.ToString() + "2-";
                label18.Text = Page_pageTolable.ToString() + "3-";
                label17.Text = Page_pageTolable.ToString() + "4-";
                label16.Text = Page_pageTolable.ToString() + "5-";
                label15.Text = Page_pageTolable.ToString() + "6-";
                label14.Text = Page_pageTolable.ToString() + "7-";
                label13.Text = Page_pageTolable.ToString() + "8-";
                label12.Text = Page_pageTolable.ToString() + "9-";
                label11.Text = (Page_pageTolable + 1).ToString() + "0-";
            }
            //最大页数应当限制为99，超过99页将会出现显示异常


        }

        private string str_transform(string str)  //格式编排
        {
            string str1 = str.Replace(" ", "").Replace("\n", "");
            int str1_len = str1.Length;
            string str2 = "";

            int num_extra = str1_len % 4;//定义传进来的数码按4个一组多余的数码的个数。
            string str_extra = str1.Substring(str1_len - num_extra, num_extra);//将多余的数码存起来
            str1_len = str1_len - num_extra;   //更新去掉多余的数码的数码字符串的长度
            str1 = str1.Substring(0, str1_len);    //更新去掉多余的数码的数码字符串


            for (int ai = 0; ai < str1_len; ai = ai + 4)    //编排格式
            {

                str2 = str2 + " " + str1.Substring(ai, 4);
                if (ai % 20 == 16) str2 = str2 + " ";   //如果是一行的第5组则加一个空格，如果是一行的第10组则加一个换行
                if (ai % 40 == 36) str2 = str2 + "\n";
            }
            str2 = str2 + " " + str_extra;//将多余的数码再加上
            return str2;   //返回编排好格式的数码
        }

        private void richTextBox2_TextChanged(object sender, EventArgs e)  //监控用户每次的输入，实时调整页数
        {
            HideCaret(((RichTextBox)sender).Handle);  //禁用富文本框中的光标
            len2 = user_input.Length;
            if (len2 == 2)
            {                         //如果用户开始输入，则开始计时，第一个字符为空格，用户输入一个字符后，总字符为2时开始计时
                flag_begin = flag_begin + 1;       //避免重复开始计时
                startTime = DateTime.Now;
            }
            if (flag_begin == 1)                  //lflag_begin为开始计时的标志                                                      
                len1 = len2;                     //len1为计时累加的标志                             


            // label27.Text = user_input.Length.ToString();

            shuzu2[page] = user_input;     //将用户输入的数码存起来
            if (user_input.Length == 400)  //判断用户是否将本页内容输入完毕
            {
                page = page + 1;        //如果这一页满了，页码就加一，跳到下一页
                pageTolable(page);      //显示每一页的lable标签值
                richTextBox1.Text = shuzu[page];//显示要输入的内容
                user_input = "";          //将用户每页输入内容清空
                richTextBox2.Text = "";  //将文本框清空               
            }

        }

        private void richTextBox2_KeyPress(object sender, KeyPressEventArgs e)//接收用户键盘按下的字符，实时调整数码格式
        {
            if (e.KeyChar >= 48 & e.KeyChar <= 57)    //接收0-9之间的数字符号，并进行处理
            {
                user_input = user_input + e.KeyChar;
                e.Handled = true;      //对事件标记处理完毕，否则系统会发出警告声
            }

            if (e.KeyChar < 48 || e.KeyChar > 57)   //接收除阿拉伯数字之外符号
                e.Handled = true;         //对事件标记处理完毕，否则系统会发出警告声

            if (e.KeyChar == '\b')                 //接收退格键符号，并进行处理
            {
                if (user_input.Length >= 1)
                    user_input = user_input.Substring(0, user_input.Length - 1);
                if (user_input.Length == 0)
                    user_input = " ";
                e.Handled = true;         //对事件标记处理完毕，否则系统会发出警告声
            }
            richTextBox2.Text = str_transform(user_input);   //将格式编排完毕的数码显示在文本框中
            richTextBox2.AppendText("_");
            shumalist.Add(user_input);                            //记录用户输入的过程
            timelist.Add(ExecDateDiff(startTime, DateTime.Now));    //记录用户输入的时间
            startTime = DateTime.Now;

        }

        private void button2_Click(object sender, EventArgs e) //校验按钮
        {
            flag_time_stop = 1;
            len2 = 0;
            show_check();
        }

        private void button1_Click(object sender, EventArgs e)  //开始按钮，开始数码练习
        {
            int t;
            if (checkBox1.Checked == false)
                t = 99999;
            else
                t = (int)numericUpDown1.Value;
            b = t * 60;

            flag_time_stop = 0;

            shumalist.Clear();//清空动态数组
            timelist.Clear();

            if (flag_bn != 0)                       //标签
            {
                MessageBox.Show("已重新开始");
            }
            user_input = "";         //定义当前富文本框用户输入的内容
            sudu_ = 0;
            time_ = 0;              //
            len1 = 1;
            len2 = 0;                 //定义两个与计时相关的标志
            page = 1;                           //定义页码，初始为第一页
            flag_begin = 0;                     //定义计时开始标志
            user_input_nums = 0;            //定义用户输入的数码组数
            shuzu = new string[1024];      //定义生成数码
            shuzu2 = new string[1024];     //定义用户输入的数码
            conduct_shuzu();
            pageTolable(page);      //显示每一页的lable标签值
            richTextBox1.Text = shuzu[page];//显示要输入的数码  
            richTextBox2.Text = "";
            s = 0;
            flag_bn = flag_bn + 1;





        }

        private void button4_Click(object sender, EventArgs e)//退出按钮
        {
            this.Close();

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button5_Click(object sender, EventArgs e)//重新启动按钮
        {
            Application.Exit();
            System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location);
        }

       

        void reappear()//再现过程线程
        {
            while (true)
            {
                if (flag_reappear == 1)
                {
                    richTextBox2.Text = "";
                    int times = shumalist.Count;
                    int temp = flag_bn;
                    for (int i_re = 0; i_re < times; i_re++)
                    {
                        if (temp != flag_bn)        //如果再现过程的时候按下了开始按钮，则退出再现过程
                            break;
                        int time000 = Convert.ToInt32(timelist[i_re]);
                        Thread.Sleep(time000);
                        richTextBox2.Text = str_transform((string)shumalist[i_re]);
                    }
                    flag_reappear = 0;
                }
                Thread.Sleep(1000);
            }
        }

        private void label27_Click(object sender, EventArgs e)
        {

        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void button5_Click_1(object sender, EventArgs e)
        {

        }

        private void button3_Click_1(object sender, EventArgs e)//再现过程按钮
        {
            flag_reappear = 1;
        }

        void show_check()  //显示校验窗口
        {
            数码测试结果窗体 form2 = new 数码测试结果窗体(user_input_nums, shuzu, shuzu2, sudu_, time_);
            form2.Show();
        }

        double ExecDateDiff(DateTime dateBegin, DateTime dateEnd)
        {
            TimeSpan ts1 = new TimeSpan(dateBegin.Ticks);
            TimeSpan ts2 = new TimeSpan(dateEnd.Ticks);
            TimeSpan ts3 = ts1.Subtract(ts2).Duration();

            //你想转的格式
            return ts3.Milliseconds;
        }
    }
}
